package es.us.lsi.daw.util;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import net.sf.json.JSONObject;
import net.sf.json.JsonConfig;
import net.sf.json.util.PropertyFilter;

import org.hibernate.collection.internal.PersistentMap;
import org.springframework.ui.ModelMap;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import es.us.lsi.daw.annotations.NoProcesarJson;

public class UtilBinding implements Serializable{

	private static final long	serialVersionUID	= -4506728476191656629L;
	
	public static final String JSON_INCLUIDOS = "jsonIncluidos";
	public static final String JSON_EXCLUIDOS = "jsonExcluidos";
	public static final String JSON_INCLUIDOS_NAVEGACION = "jsonIncluidosNavegacion";
	
	public JsonConfig getJsonConfigComun() {
        JsonConfig config =  new JsonConfig();	  
        //config.setExcludes(new String[]{"getAuthorities","authorities","Authorities"});
        config.setJsonPropertyFilter(new PropertyFilter(){		                    	
        	public boolean apply(Object source,String name, Object value) {	                    			                    		
        		try{	                    			
        			HttpServletRequest servletRequest = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        			Class c = source.getClass();	                    			
        			if(c.equals(JSONObject.class) || c.equals(HashMap.class) || c.equals(ModelMap.class) || c.equals(PersistentMap.class))
        				return false;
        			Field f = Util.obtenerCampoClaseSuperClases(c,name);	                    			
        				                    			
        			//Los elementos de la lista 'incluidos' serán tratados por json.
        			List<String> lstIncluidos = (List<String>)servletRequest.getAttribute(JSON_INCLUIDOS);
        			//Los elementos de la lista 'excluidos' serán ignorados por json.
        			List<String> lstExcluidos = (List<String>)servletRequest.getAttribute(JSON_EXCLUIDOS);
        			//La lista 'jsonIncluidosNavegacion', contiene un conjunto de cadenas de textos,
        			//donde cada una de las cadenas tiene una estructura como la siguiente:
        			//--> nombreDeLaClase + . + atributo (nombreDeLaClase.atributo). 
        			//Con esto obtenemos el control total de la navegación de json, evitando así,
        			//los fallos debido a la navegación en bucle.
        			List<String> lstIncluidosNavegacion = (List<String>)servletRequest.getAttribute(JSON_INCLUIDOS_NAVEGACION);
        			
        			if(lstExcluidos != null && lstExcluidos.contains(name)){
        				return true;
        			}
        			if(lstIncluidosNavegacion == null && lstIncluidos != null && lstIncluidos.contains(name)){	                    				
        					return false;	                    				
        			}
        			if(lstIncluidosNavegacion != null && lstIncluidosNavegacion.contains(source.getClass().getSimpleName()+ "." + name))
        				return false;
        			if(f != null && (f.getType().isPrimitive() || f.getType().equals(String.class) || f.getType().equals(Long.class) || f.getType().equals(Boolean.class) || f.getType().equals(Float.class) || f.getType().equals(Integer.class)
        					|| f.getType().equals(Double.class))){	                    				
        				return false;
        			}
        			if(f != null && f.isAnnotationPresent(NoProcesarJson.class))
        				return true;
        		}catch (Exception e) {
					e.printStackTrace();
				}	                    		
        			return true;
        		}
        	});
        return config;
    }

}
